package com.chinanet.service.faultanticipate.imp;

import com.chinanet.entry.faultanticipate.*;
import com.chinanet.entry.faultanticipate.manager.QRolle;
import com.chinanet.entry.faultanticipate.manager.QTeam;
import com.chinanet.event.entry.RecordExecuteEvent;
import com.chinanet.oracle.entry.OModel;
import com.chinanet.oracle.service.OModelService;
import com.chinanet.repository.faultanticipate.BranchRepository;
import com.chinanet.repository.faultanticipate.DetailRepository;
import com.chinanet.repository.faultanticipate.ModelRepository;
import com.chinanet.repository.faultanticipate.RecordRepository;
import com.chinanet.service.faultanticipate.IDetailService;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.jpa.JPQLQuery;
import com.querydsl.jpa.impl.JPAQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Service
public class DetailServiceImpl implements IDetailService {

    @Autowired
    private DetailRepository detailRepository;

    @Autowired
    private BranchRepository branchRepository;

    @Autowired
    private RecordRepository recordRepository;

    @Autowired
    private ModelRepository modelRepository;

    @Autowired(required = true)
    private OModelService oModelService;

    @PersistenceContext
    private EntityManager em;

    @Override
    @Transactional
    public long save(Detail detail, Model model, Branch branch) {
        // 保存
        detail = detailRepository.save(detail);
        branch = branchRepository.save(branch);
        Record record = new Record();
        //关联
        record.setModelId(model.getId());
        record.setComment("新建分支" + branch.getName());
        record.setBranch(branch);
        branch.setDetail(detail);
        recordRepository.save(record);
        branchRepository.save(branch);
        return detail.getId();
    }

    @Override
    @Transactional
    public long load(Detail detail, Model model, Branch branch, BigDecimal aim) {
        // 保存
        detail = detailRepository.save(detail);
        branch = branchRepository.save(branch);
        Record record = new Record();
        //关联
        record.setModelId(model.getId());
        record.setComment("新建分支" + branch.getName());
        record.setBranch(branch);
        branch.setDetail(detail);
        recordRepository.save(record);
        branchRepository.save(branch);

        Iterator<OModel> oModels = oModelService.findHistory(aim).iterator();
        while (oModels.hasNext()) {
            OModel e = oModels.next();
            System.out.println(e.getName());
            Model historyModel = new Model();
            Record historyRecord = new Record();
            historyModel.setSelect(e.getIsElect());
            historyModel.setmType(e.getmType().toString());
            historyModel.setInitParam(e.getOrigin());
            historyModel.setDelmark(e.getDelmark());
            historyModel.setContent(e.getJson());
            historyModel.setCondition(e.getCondition());
            historyModel = modelRepository.save(historyModel);
            //关联
            historyRecord.setModelId(historyModel.getId());
            historyRecord.setComment("历史" + e.getTime());
            historyRecord.setBranch(branch);
            recordRepository.save(historyRecord);
        }

        // 历史记录
        return detail.getId();
    }

    @Transactional
    @Override
    public long copy(Detail detail) {
        Detail oidDetail = detailRepository.findById(detail.getId()).get();
        Branch branch = branchRepository.findByDetailAndIsMaster(oidDetail.getId(), true);
        Record record = recordRepository.getBylately(branch.getId());
        Model model = modelRepository.findById(record.getModelId()).get();
        // 创建新Model
        Model newModel = new Model();
        newModel.setBranch(model.getBranch());
        newModel.setCondition(model.getCondition());
        newModel.setContent(model.getContent());
        newModel.setDelmark(model.getDelmark());
        newModel.setInitParam(model.getInitParam());
        newModel.setmType(model.getmType());
        newModel.setSelect(model.getSelect());
        newModel.setsId(model.getsId());
        // 创建新branch
        Branch newBranch = new Branch();
        newBranch.setDescription(detail.getDescription());
        newBranch.setIsMaster(true);
        newBranch.setName(detail.getName());
        newBranch.setLastBranch(branch);

        // 创建新Record
        Record newRecord = new Record();
        newRecord.setComment(detail.getDescription());
        newRecord.setModelId(modelRepository.save(newModel).getId());


        // 新建Detail
        Detail newDetail = new Detail();
        newDetail.setName(detail.getName());
        newDetail.setDescription(detail.getDescription());
        newDetail.setDelmark(oidDetail.getDelmark());
        newDetail.setmType(oidDetail.getmType());

        // 设置关联
        newBranch.setDetail(newDetail);
        List<Branch> branches = new ArrayList<Branch>();
        List<Record> records = new ArrayList<Record>();
        branches.add(newBranch);
        records.add(newRecord);
        newDetail.setBranches(branches);
        return detailRepository.save(newDetail).getId();
    }

    @Override
    @Transactional
    public Record getRecordByDetail(long detailId) {
        Branch branch = branchRepository.findByDetailAndIsMaster(detailId, true);
        return recordRepository.getBylately(branch.getId());
    }

    @Override
    @Transactional
    public long updateByBranch(Detail detail, Model model, Branch branch, Branch lastBranch) {
        // 获取对象
        detail = detailRepository.findById(detail.getId()).get();
        branch = branchRepository.save(branch);
        lastBranch = branchRepository.findById(lastBranch.getId()).get();
        model = modelRepository.findById(model.getId()).get();
        Record record = new Record();
        //关联
        record.setModelId(model.getId());
        record.setComment("新建分支" + branch.getName());
        record.setBranch(branch);
        branch.setDetail(detail);
        branch.setLastBranch(lastBranch);
        recordRepository.save(record);
        branchRepository.save(branch);
        return branch.getId();
    }

    @Async
   // @TransactionalEventListener
    @EventListener
    public void handleAfterRecordExecuteComplete(RecordExecuteEvent event){
        System.out.println("监听成功");
        Detail detail=detailRepository.findById(event.getId()).get();
        detail.setModifiesTimes(detail.getModifiesTimes()+1);
        detailRepository.save(detail);
    }

    @Override
    public Page<Detail> getAllByRole(String search,long roleId, Pageable pageable) {
        Page<Detail> details=null;
        if (search != null) {
            // Note this to support ohter non-English System
            // 支持非英文的服务器环境
            // 虽然是有三个操作符号，不过现在只支持：
            Pattern pattern = Pattern.compile("(\\w+?)(:|<|>)(\\w+?),",Pattern.UNICODE_CHARACTER_CLASS);
            Matcher matcher = pattern.matcher(search + ",");
            while (matcher.find()) {
                System.out.println(matcher.group(3));
                details=detailRepository.getAllByRole("d."+matcher.group(1),"\""+matcher.group(3)+"\"",roleId,pageable);
            }
        }else{
            details=detailRepository.getAllByRole(roleId,pageable);
        }
        System.out.println("数据成功");
        return details;
    }

    @Override
    @Transactional
    public Page<Detail> getAllByRole(long roleId, Pageable pageable) {
        QDetail detail=QDetail.detail;
        QTeam team=QTeam.team;
        QRolle rolle=QRolle.rolle;
        JPQLQuery<QDetail> query=new JPAQuery(em);
        BooleanBuilder predicate = new BooleanBuilder();
        predicate.and(rolle.id.eq(roleId));
        query.from(detail).join(detail.teams,team).join(team.rolles,rolle).where(predicate);
        return detailRepository.findAll(query,pageable);
    }

    @Override
    @Transactional
    public long updateByCopy(Record record, Branch currentBranch) {
        // 获取对象
        currentBranch = branchRepository.findById(currentBranch.getId()).get();
        //关联
        record.setBranch(currentBranch);
        record = recordRepository.save(record);
        return record.getId();
    }
}